home *** CD-ROM | disk | FTP | other *** search
Wrap
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTDocInfo.m // SUMMARY: Implementation of eTNavinfo objects; stringTable I/O. // SUPERCLASS: Object:HashTable:NXStringTable:eTDocInfo // PROTOCOLS: None // AUTHOR: Rohit Khare // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION // eTDocInfo is built atop NXStringTable, but implementation should be // completely private and abstracted away. /////////////////////////////////////////////////////////////////////////////// // HISTORY // 07/20/94: Added LaTeX support. // 07/10/94: Added support for HTML header/trailer writing // 01/10/94: Created. See Actors/eTNavinfo /////////////////////////////////////////////////////////////////////////////// #import "eTDocInfo.h" #import "Navigator.h" @implementation eTDocInfo // char path[MAXPATHLEN]; // BOOL readOnly; // long docID; // Accessor Methods - (long) docID {return docID;} - (NXAtom) docIDStr {return [self valueForStringKey:DOCID];} - (NXAtom) title {return [self valueForStringKey:TITLE];} - (NXAtom) author {return [self valueForStringKey:AUTHOR];} - (NXAtom) agent {return [self valueForStringKey:AGENT];} - (NXAtom) parent {return [self valueForStringKey:PARENT];} - (NXAtom) peers {return [self valueForStringKey:PEERS];} - (NXAtom) keywords {return [self valueForStringKey:KEYWORDS];} - (NXAtom) rtfComments {return [self valueForStringKey:COMMENTS];} // ASCII-coded RTF source of comment field - (STR) comments { // ASCII contents of comment field static char comments[1024]; NXStream *stream; id theText = [NXApp sharedText]; stream = NXOpenMemory([self valueForStringKey:COMMENTS], strlen([self valueForStringKey:COMMENTS]), NX_READONLY); [theText readRichText:stream]; NXClose(stream); [theText getSubstring:comments start:0 length:1023]; comments[1023]=0; return comments; } - (NXAtom) valueOf: (NXAtom) theQuery { NXAtom tmp = [self valueForStringKey:theQuery]; return (tmp ? tmp : NXUniqueString("")); } // Dynamic Bits - (STR) path {return path;} - (BOOL) readOnly {return readOnly = (BOOL) access(path, W_OK);} // Setter Methods - setPath:(const char *) newPath { if ([self title] == NXUniqueString("Unsaved Doc")) { char tmp[MAXPATHLEN]; // C Programmer's Disease strncpy(tmp, rindex(newPath, '/')+1, MAXPATHLEN); *rindex(tmp, '.') = 0; [self setTitle:tmp]; } strncpy(path, newPath, MAXPATHLEN); // how do we tell eTNavinfoUI its info has been invalidated? return self; } - setTitle:(const char *) newTitle {[self insertKey:TITLE value:NXUniqueString(newTitle)]; return self;} - setAuthor:(const char *) newAuthor {[self insertKey:AUTHOR value:NXUniqueString(newAuthor)]; return self;} - setAgent:(const char *) newAgent {[self insertKey:AGENT value:NXUniqueString(newAgent)]; return self;} - setParent:(const char *) newParent // ASCII-coded docID of parent etNavinfo {[self insertKey:PARENT value:NXUniqueString(newParent)]; return self;} - setPeers:(const char *) newPeers // ASCII-coded, space between each docID {[self insertKey:PEERS value:NXUniqueString(newPeers)]; return self;} - setKeywords:(const char *) newKeywords {[self insertKey:KEYWORDS value:NXUniqueString(newKeywords)]; return self;} - setComments:(const char *) newComments // ASCII-coded RTF source of comment field {[self insertKey:COMMENTS value:NXUniqueString(newComments)]; return self;} - bindKey:(const char *) newKey to: (const char *) newVal {[self insertKey:NXUniqueString(newKey) value:NXUniqueString(newVal)]; return self;} // Searching Methods - (BOOL) searchFor:(NXAtom) regex in:(NXAtom) field // field == "*" means any { // Note that we search the RTF-coded comments field // -- not the ascii-filtered version BOOL found = NO; //special-case speed-up // REWRITE REST OF CODE TO USE 2 RE_COMP's RATHER THAN !recmp if (re_comp(regex)) return NO; if ((field == ANYFIELD) && (re_exec([self valueForStringKey:TITLE]) || re_exec([self valueForStringKey:PARENT]) || re_exec([self valueForStringKey:KEYWORDS]) || re_exec([self valueForStringKey:DOCID]) || re_exec([self valueForStringKey:AUTHOR]) || re_exec([self valueForStringKey:AGENT]) || re_exec([self valueForStringKey:PEERS]) || re_exec([self valueForStringKey:COMMENTS]))) return YES; if (!recmp(field, DOCID)) found |= !strcmp(regex, [self valueForStringKey:DOCID]); if (!found && !strcmp(field, PARENT)) found |= !strcmp(regex, [self valueForStringKey:PARENT]); if (!found && !strcmp(field, TITLE)) found |= !strcmp(regex, [self valueForStringKey:TITLE]); if (!found && !strcmp(field, AUTHOR)) found |= !strcmp(regex, [self valueForStringKey:AUTHOR]); if (!found && !strcmp(field, AGENT)) found |= !strcmp(regex, [self valueForStringKey:AGENT]); if (!found && !strcmp(field, PEERS)) found |= !strcmp(regex, [self valueForStringKey:PEERS]); if (!found && !strcmp(field, KEYWORDS)) found |= !strcmp(regex, [self valueForStringKey:KEYWORDS]); if (!found && !strcmp(field, COMMENTS)) found |= !strcmp(regex, [self valueForStringKey:COMMENTS]); return found; } // Input/Output Methods - init { char idStr[9]; struct passwd *p; [super init]; path[0] = 0; docID = [NXApp uniqueID]; sprintf(idStr,"%x", docID); [self insertKey:DOCID value:(char *)NXUniqueString(idStr)]; [self insertKey:TITLE value:NXUniqueString("Unsaved Doc")]; p = getpwuid(getuid()); if (p->pw_name) [self insertKey:AUTHOR value:NXUniqueString(p->pw_gecos)]; else [self insertKey:AUTHOR value:NXUniqueString("Author's Name")]; [self insertKey:AGENT value:NXUniqueString("")]; [self insertKey:PARENT value:NXUniqueString("")]; [self insertKey:PEERS value:NXUniqueString("")]; [self insertKey:KEYWORDS value:NXUniqueString("Index Terms")]; [self insertKey:COMMENTS value:NXUniqueString("{\\rtf0\\ansi{\\fonttbl\\f1\\fnil Times-Roman;\\f2\\fswiss Helvetica;}\n\\margl40\n\\margr40\n\\pard\\tx520\\tx1060\\tx1600\\tx2120\\tx2660\\tx3200\\tx3720\\tx4260\\tx4800\\tx5320\\f1\\b0\\i\\ulnone\\fs24\\fc0\\cf0 Rich-Text \n\\b comments\n\\b0 about this document\n}\n")]; readOnly = NO; [[NXApp navigator] registerNavinfo:self]; return self; } - free { //sanity check char * foo = [self valueForStringKey:DOCID]; if (foo) sscanf(foo, "%x", &docID); if (foo && [[NXApp navigator] navinfoFor:docID] != self) return [super free]; return self; } - initFromDoc:(const STR) pathname { char navinfoPath[MAXPATHLEN]; [super init]; strncpy(path, pathname, MAXPATHLEN); sprintf(navinfoPath, "%s/%s", path, NAVINFO); if (access(navinfoPath, R_OK | F_OK)) { // backward-compatibility with PR1 documents. sprintf(navinfoPath, "%s/etNavinfo", path); } if (access(navinfoPath, R_OK | F_OK)) { [NXApp delayedFree:self]; return nil; } if (![self readFromFile:navinfoPath]) { [NXApp delayedFree:self]; return nil; } sscanf([self valueForStringKey:DOCID], "%x", &docID); if ([[NXApp navigator] navinfoFor:docID]){ [NXApp delayedFree:self]; return [[NXApp navigator] navinfoFor:docID]; } else [[NXApp navigator] registerNavinfo:self]; return self; } - writeToDoc:(const STR) pathname // Passing in null is ok; uses last path { char navinfoPath[MAXPATHLEN]; sprintf(navinfoPath, "%s/%s", pathname ? pathname : path, NAVINFO); [self writeToFile:navinfoPath]; return self; } - writeToDoc { return [self writeToDoc:NULL];} // "Hidden" API - writeHTMLHeader:(NXStream *)s { char tmp[MAXPATHLEN]; long dID; id dNI; id NIlist; NXAtom peers; int i; NXPrintf(s,"<HEAD>\n<TITLE>%v</TITLE>\n",[self title]); // does eTNavinfo have etfLink objects handy? -- no, it doesn't. strcpy(tmp, [self parent]); sscanf(tmp, "%x", &dID); dNI = [[NXApp navigator] navinfoFor:dID]; if (dNI) { strcpy(tmp, [dNI path]); *rindex(tmp,'.')=0; NXPrintf(s,"<LINK HREF=\"../%s.htmd/TXT.html\" REL=\"Parent\" TITLE=\"%v\">\n", rindex(tmp,'/')+1,[dNI title]); } NIlist = [[NXApp navigator] query:[self docIDStr] field:PARENT]; i = [NIlist count]; for (;i;i--) { strcpy(tmp, [[NIlist objectAt:(i-1)] path]); *rindex(tmp,'.')=0; NXPrintf(s,"<LINK HREF=\"../%s.htmd/TXT.html\" REL=\"Child\" TITLE=\"%v\">\n", rindex(tmp,'/')+1,[[NIlist objectAt:(i-1)] title]); } // continue for "peer" documents? // for peers, we get a list of doc IDs that are space-separated i=0; peers = [self peers]; while (peers[i] && (1 == sscanf(peers+i,"%x",&dID))) { dNI = [[NXApp navigator] navinfoFor:dID]; if (dNI) { strcpy(tmp, [dNI path]); *rindex(tmp,'.')=0; NXPrintf(s,"<LINK HREF=\"../%s.htmd/TXT.html\" REL=\"Peer\" TITLE=\"%v\">\n", rindex(tmp,'/')+1,[dNI title]); } while(peers[i] && (peers[i] != ' ')) i++; //skip ahead } NXPrintf(s,"</HEAD>\n"); return self; } - writeHTMLTrailer:(NXStream *)s { char tmp[MAXPATHLEN]; long dID; id dNI; id NIlist; NXAtom peers; int i; // we should try to check the user's preferences here // we use a hole to tunnel through to a switch in the UI // if (trailerSw) // write HR, then parent, peers, then author, date, then NXPrintf(s,"\n\n<!-- TRAILER -->\n<HR>\n<DL COMPACT>\n"); strcpy(tmp, [self parent]); sscanf(tmp, "%x", &dID); dNI = [[NXApp navigator] navinfoFor:dID]; if (dNI) { strcpy(tmp, [dNI path]); *rindex(tmp,'.')=0; NXPrintf(s,"\n<DT>Parent:</DT>\n<DD><A HREF=\"../%s.htmd/TXT.html\">%v</A></DD>\n", rindex(tmp,'/')+1,[dNI title]); } NIlist = [[NXApp navigator] query:[self docIDStr] field:PARENT]; i = [NIlist count]; if ([NIlist count]) NXPrintf(s,"\n<DT>Children:</DT>\n"); for (;i;i--) { strcpy(tmp, [[NIlist objectAt:(i-1)] path]); *rindex(tmp,'.')=0; NXPrintf(s,"\n<DD><A HREF=\"../%s.htmd/TXT.html\">%v</A></DD>\n", rindex(tmp,'/')+1,[[NIlist objectAt:(i-1)] title]); } // for peers, we get a list of doc IDs that are space-separated i=0; peers = [self peers]; if(strlen(peers)) NXPrintf(s,"\n<DT>See Also:</DT>\n");; while (peers[i] && (1 == sscanf(peers+i,"%x",&dID))) { dNI = [[NXApp navigator] navinfoFor:dID]; if (dNI) { strcpy(tmp, [dNI path]); *rindex(tmp,'.')=0; NXPrintf(s,"\n<DD><A HREF=\"../%s.htmd/TXT.html\">%v</A></DD>\n", rindex(tmp,'/')+1,[dNI title]); } while(peers[i] && (peers[i] != ' ')) i++; //skip ahead } NXPrintf(s,"</DL>\n"); NXPrintf(s,"<HR><A HREF=\"http://www.etext.caltech.edu/\">Created by the eText Engine, version %v</A><P>%v\n", [NXApp version], [NXApp date]); return self; } - writeLaTeXHeader:(NXStream *)s { NXPrintf(s, "\n\\author{%w}\n\\title{%w}\n\\maketitle\n",[self author], [self title]); return self; } @end